package com.learn.authentication.service.impl;

import com.learn.authentication.pojo.LogUser;
import com.learn.authentication.pojo.User;
import com.learn.authentication.service.LoginService;
import com.learn.authentication.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author DJJ_F
 * @version 1.0
 * @date 2025/04/06
 * @description
 */
@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    RedisTemplate<Object, Object> redisTemplate;
    public String login(User user) {
        /*
        先进行认证，使用AuthenticationManager的authenticate()方法
        因为上面的方法需要传入Authentication认证对象，而Authentication又是个接口
        所以我们需要他的实现类UsernamePasswordAuthenticationToken对象
        他需要两个参数用户名和密码
        */
        // 这是未认证的Authentication对象
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        // 这是已认证的Authentication对象，通过authenticationManager来获取
        // 存入 SecurityContextHolder，供后续权限检查使用。
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if(Objects.isNull(authenticate)) {
            throw new RuntimeException("登录失败");
        }
        // 这里可以看到principal就是UserDetails对象，credentials就是密码
//        System.out.println(authenticate);
        // 根据用户id获取jwt
        LogUser loginUser = (LogUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        String jwt = JwtUtil.genToken(userId, user.getPassword());
        // 存到redis里面, 并设置过期时间，注意存的是loginUser里面有权限信息
        redisTemplate.opsForValue().set("login_" + userId, loginUser, 7, TimeUnit.DAYS);
        return jwt;
    }

    @Override
    public void logout() {
        // 从authentication获取userId
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 能进来就说明认证通过了，不用判空
        Long id = ((LogUser) authentication.getPrincipal()).getUser().getId();
        // 删除redis的记录
        redisTemplate.delete("login_" + id);
    }
}
